package face.pay.open.material.service.impl;

import com.face.pay.IPayConfigServer;
import com.face.pay.SecurityConfig;
import com.face.pay.WxApiConfig;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayRequest;
import com.github.wxpay.sdk.WXPayUtil;
import face.pay.dao.FileInfoDao;
import face.pay.dao.MchApplymentInfoDao;
import face.pay.dao.OemConfigInfoDao;
import face.pay.dao.OemInfoDao;
import face.pay.entity.MchApplymentInfo;
import face.pay.open.material.service.IMchApplymentService;
import face.pay.open.server.CertInfo;
import face.pay.open.server.CertficatesServer;
import face.pay.open.util.request.ApiRequestParam;
import face.pay.open.util.request.ErrorCode;
import face.pay.open.validate.ApiParamValidate;
import face.pay.util.RSAEncryp;
import face.pay.util.ResultMessage;
import face.pay.util.bean.JavaBeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @Auther: zkj
 * @Date: 2019/8/27 14:36
 * @Description:
 */
@Service
@Slf4j
public class MchApplymentServiceimpl implements IMchApplymentService {


   private static final String domain = "api.mch.weixin.qq.com";



    @Autowired
    private ApiParamValidate apiParamValidate;

    @Autowired
    private OemConfigInfoDao oemConfigInfoDao;

    @Autowired
    private OemInfoDao oemInfoDao;

    @Autowired
    private IPayConfigServer wxApiConfigServer;

    @Autowired
    private FileInfoDao fileInfoDao;

    @Autowired
    private CertficatesServer certficatesServer;

    @Autowired
    private MchApplymentInfoDao mchApplymentInfoDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultMessage applyment(String json){

        log.info("商户进件：报文"+json);

        Integer code = ErrorCode.ERROR;

        String message  = "未知错误";

        Boolean flag= true;


        ApiRequestParam apiRequestParam  = apiParamValidate.parse(json);


        try{
            if(apiRequestParam!=null) {

                Integer oemId = apiRequestParam.getOemId();

                log.info("oemId:"+oemId);
                WxApiConfig config = wxApiConfigServer.getConfig(oemId);

                if(config==null){
                    code = ErrorCode.ERROR;
                    message ="平台配置信息不全";
                }else {

                    SecurityConfig securityConfig = config.getSecurityConfig();
                    /**
                     * 签名验证
                     * 参数验证
                     *
                     */

                    /**
                     * 商户进件的资料信息
                     */
                    Map<String, String> data = apiRequestParam.getData();

                    Boolean validate = apiParamValidate.validate(data,apiRequestParam.getSign(),securityConfig);

                    if(validate){

                        MchApplymentInfo mchApplymentInfo = (MchApplymentInfo) JavaBeanUtils.mapToBean(data, MchApplymentInfo.class);
                        /**
                         * 生成业务编码
                         */
                        String business_code = JavaBeanUtils.getMixString(12);

                        mchApplymentInfo.setBusiness_code(business_code);

                        Map<String, String> map = JavaBeanUtils.toMap(mchApplymentInfo);



                        CertInfo certInfo = this.certficatesServer.getcertficatesInfo(config);

                        String cert_sn = certInfo.getSerial_no();



                        if (StringUtils.isNotBlank(cert_sn)) {

                            map.put("version", "3.0");

                            map.put("cert_sn", cert_sn);

                            map.put("mch_id",config.getMchID());
                            map.put("sign_type", "HMAC-SHA256");

                            String nonce_str = WXPayUtil.generateNonceStr();

                            map.put("nonce_str", nonce_str);
                            String   id_card_valid_time =   mchApplymentInfo.getId_card_valid_time();

                            String[]   times = id_card_valid_time.split("[|]");
                            id_card_valid_time="[\""+times[0]+"\""+",\""+times[1]+"\"]";

                            String rate = mchApplymentInfo.getRate()+"%";

                            map.put("id_card_valid_time",id_card_valid_time);
                            map.put("rate",rate);

                            log.info("敏感字段加密");
                            /**
                             * 指定需要加密处理的字段
                             */
                            List keyList = new ArrayList();
                            keyList.add("id_card_name");
                            keyList.add("id_card_number");
                            keyList.add("contact");
                            keyList.add("account_name");
                            keyList.add("account_number");
                            keyList.add("contact_phone");
                            keyList.add("contact_email");


                            String cer_public_key =   RSAEncryp.decryptCertSN(certInfo.getAssociated_data(),certInfo.getNonce(),certInfo.getCipherText(),certInfo.getApi3key());

                            RSAEncryp.rsaEncryptByCert(map,keyList,cer_public_key);
                            /**
                             * 敏感字段加密
                             */
                            log.info("敏感字段加密结束");


                            String xml = WXPayUtil.generateSignedXml(map, config.getKey(), WXPayConstants.SignType.HMACSHA256);
                            log.info("调用微信进件接口:" + xml);
                            WXPayRequest wxPayRequest = new WXPayRequest(config);

                            String urlSuffix = "/applyment/micro/submit";

                            String result = wxPayRequest.requestOnce(domain, urlSuffix, UUID.randomUUID().toString(), xml, 8000, 6000, true);

                            log.info("微信进件接口返回结果:" + result);
                            Map<String, String> resultMap = WXPayUtil.xmlToMap(result);


                            Boolean isOk = WXPayUtil.isSuccess(resultMap);

                            if (isOk) {
                                String applyment_id = resultMap.get("applyment_id");

                                mchApplymentInfo.setApplyment_id(applyment_id);
                                mchApplymentInfo.setOemId(oemId);
                                mchApplymentInfo.setApplyment_state("AUDITING");
                                this.mchApplymentInfoDao.insert(mchApplymentInfo);


                                Map<String, String> resultData = new HashMap<>();

                                resultData.put("applyment_id", applyment_id);
                                resultData.put("business_code", business_code);

                                return   ResultMessage.createSuccess("提交资料成功",resultData);

                            } else {
                                code = ErrorCode.WX_SEND_ERROR;
                                message = resultMap.get("return_msg");
                                message += resultMap.get("err_code_des");

                            }


                        } else {
                            code = ErrorCode.ERROR;
                            message = "获取证书序列出错";
                        }
                    }else {
                            code = ErrorCode.SING_ERROR;
                            message = ErrorCode.SING_ERROR_MESSAGE;
                    }
                }
            }
        }catch (Exception e){
            log.error("进件异常",e);
            code = ErrorCode.ERROR;
        }


        return ResultMessage.createFail(message).setErrorCode(code);
    }
}
